package sketch.specs;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CatchClause;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.TryStatement;

import sketch.ast.ASTUtils;
import sketch.specs.annotation.TryCatch;

public class SketchedTryCatchBlock extends SketchedBlock  {
	
	public static final String EXCEPTION_NAME = "e$$_wrapped";
	
	public static final String EXCEPTION_TYPE = "Throwable";

	public static final String COMMENT_REPRESENTATION = TryCatch.value();
	
	public SketchedTryCatchBlock(Block realBlock) {
		super(realBlock);
	}

	@Override
	protected List<Block> replicate() {
		/**
		 * The replication process is straightforward, wrap the realBlock with
		 * try {
		 *     realBlock
		 *     fail();
		 * catch (Throwable e) {
		 *     Tracer.recordException(line num, e); //this line will be add during source code instrumentation
		 * }
		 * */
		
		Block replicate_block = ASTUtils.deepClone(this.realBlock);
		
		//new the try-catch statement
		AST ast = replicate_block.getAST();
		TryStatement tryCatch = ast.newTryStatement();
		replicate_block.delete();//remove it from parents
		tryCatch.setBody(replicate_block);
		//set the catch block
		CatchClause cc = ast.newCatchClause();
		SingleVariableDeclaration exceptDecl = ast.newSingleVariableDeclaration();
		exceptDecl.setName(ast.newSimpleName(EXCEPTION_NAME));
		exceptDecl.setType(ast.newSimpleType(ast.newSimpleName(EXCEPTION_TYPE)));
		cc.setException(exceptDecl);
		//add to the try catch block
		tryCatch.catchClauses().add(cc);
		
		//initialize a new block
		Block retBlock = ast.newBlock();
		retBlock.statements().add(tryCatch);
		
		List<Block> blocks = new LinkedList<Block>();
		blocks.add(retBlock);
		return blocks;
	}

	@Override
	protected SketchedBlock newInstance(Block block) {
		return new SketchedTryCatchBlock(block);
	}

}
